#include <SDL/SDL.h>
#include "game.h"
#include "event.h"
#include "error_mens.h"
#include "treat.h"
#include <math.h>

/**
 * \file game.c
 * Implementacao dos metodos de game
 */

/** 
 * Funcao copiada do manual do SDL soh para testes serah apagada futuramente
 */
static void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
    switch(bpp) {
        case 1:
            *p = pixel;
        break;
        case 2:
            *(Uint16 *)p = pixel;
        break;
        case 3:
            if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
                p[0] = (pixel >> 16) & 0xff;
                p[1] = (pixel >> 8) & 0xff;
                p[2] = pixel & 0xff;
            } else {
                p[0] = pixel & 0xff;
                p[1] = (pixel >> 8) & 0xff;
                p[2] = (pixel >> 16) & 0xff;
            }
        break;
        case 4:
            *(Uint32 *)p = pixel;
        break;
    }
}

Mix_Music *m = NULL;
Mix_Music *e = NULL;
static void free_song() {
    if(m) Mix_FreeMusic(m);
    Mix_CloseAudio();
}

static void set_song(Game *g) {
    if(g) {
        Mix_OpenAudio(44100, AUDIO_S16, 2, 4096);
        g->music = Mix_LoadMUS("mus.mp3");
        if(g->music) {
            printf("Entrei na musica\n");

            Mix_PlayMusic(g->music, 0);

            Mix_HookMusicFinished(free_song);
            m = g->music;
        }
    }
}

/** Create entity */
static int create_entity(Game *g) {
    int x, y;
    Uint32 green;
    int count;

    if(g)
        printf("tem g em %s\n", __FUNCTION__);
    g->entity = (Entity*) malloc (sizeof(Entity) * (10 + 10 / g->stage));
    g->entity->frames[0] = SDL_LoadBMP("../frames/novos/f1.bmp");
    SDL_SetColorKey(g->entity->frames[0],
             SDL_SRCCOLORKEY, SDL_MapRGB(g->entity->frames[0]->format, 0, 0, 0));
    /**
    g->entity->frames[1] = SDL_LoadBMP("../frames/f2.bmp");
    g->entity->frames[2] = SDL_LoadBMP("../frames/f3.bmp");
    g->entity->frames[3] = SDL_LoadBMP("../frames/f4.bmp");
    g->entity->frames[4] = SDL_LoadBMP("../frames/f3.bmp");
    g->entity->frames[5] = SDL_LoadBMP("../frames/f3.bmp");
    **/
    g->entity->xy_hw.x = 25;
    g->entity->xy_hw.y = 270;

    /* Map the color yellow to this display (R=0xff, G=0xFF, B=0x00)
    *        Note:  If the display is palettized, you must set the palette first.
    **/
    green = SDL_MapRGB(g->screen->format, 0x00, 0xff, 0x00);
    x = 20;
    y = 125;
    /* Lock the screen for direct access to the pixels */
    if(SDL_MUSTLOCK(g->screen)) {
        if ( SDL_LockSurface(g->screen) < 0 ) {
            fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
            return;
        }
    }

    for(x = 0; x < 220; x++) {
        y = sqrt(201 * 201 - pow(x - 225, 2)) + 300;
        putpixel(g->screen, x, y, green);
    }

    for(x = 580; x < 800; x++) {
        y = sqrt(201 * 201 - pow(-x + 575 , 2)) + 300;
        putpixel(g->screen, x, y, green);
    }

    if(SDL_MUSTLOCK(g->screen)) {
        SDL_UnlockSurface(g->screen);
    }
    /* Update just the part of the display that we've changed */
    SDL_UpdateRect(g->screen, 0, 0, 800, 600);
    /* set_song(g); */

    // g->entity[1].frames[0] = SDL_LoadBMP("../frames/plateia.bmp"); 
    // g->entity[1].xy_hw.x = 25;
    // g->entity[1].xy_hw.y = 270;
    // g->entity[1].xy_hw.w = g->entity[1].frames[0]->w;
    // g->entity[1].xy_hw.h = g->entity[1].frames[0]->h;
    // SDL_BlitSurface(g->entity[1].frames[0], NULL, g->screen, &(g->entity[1].xy_hw));
    // SDL_UpdateRect(g->screen, g->entity[1].xy_hw.x, g->entity[1].xy_hw.y, g->entity[1].frames[0]->w, g->entity[1].frames[0]->h); 
    return 0;
}

static int create_world(Game *g)
{
    create_entity(g);
}

static int create_menu(Game *g)
{

}

Game *create_game()
{
    Uint32 i = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER; 
    int count;

    /* Alloca principal estrutura do jogo */
    Game *g = (Game*) malloc (sizeof(Game));
    if(g == NULL) {
        P_ERROR("Erro na alocacao de Game\n");
        exit(-1);
    }

    /* Inicializa o jogo */
    if(SDL_Init(i) < 0) {
        P_ERROR("Erro na inicializacao do sistema SDL\n");
        exit(-1);
    }

    /* Inicializa video */
    g->height = 600;
    g->width = 800;
    SDL_WM_SetCaption("Sk4t3", "Sk4t3");
    // g->screen = SDL_SetVideoMode(g->width, g->height, 16, SDL_DOUBLEBUF | SDL_FULLSCREEN);
    g->screen = SDL_SetVideoMode(g->width, g->height, 16, SDL_DOUBLEBUF);
    if(g->screen == NULL) {
        P_ERROR("Erro na inicilizacao do video\n");
        exit(-1);
    }
    g->stage = 1;
    g->level = 0;
    g->entity = NULL;
    for(count = 0; count < END_TS; count++)
        g->ticks[count] = 0;
    /* g->envComp = NULL; */
    create_world(g);
    SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);

    return g;
}

int destroy_game(Game *g)
{
    if(g) {
        SDL_FreeSurface(g->entity->frames[0]); 
        SDL_FreeSurface(g->entity->frames[1]); 
        /**
        SDL_FreeSurface(g->entity->frames[2]); 
        SDL_FreeSurface(g->entity->frames[3]); 
        SDL_FreeSurface(g->entity->frames[4]); 
        SDL_FreeSurface(g->entity->frames[5]); 
        **/
        SDL_FreeSurface(g->entity[1].frames[0]);
        free(g->entity);
        free(g);
    }
}

int render_game(Game *g)
{
    int i;
    SDL_Rect loc; 

    for(i = 0; i < 1;) {
        g->entity->xy_hw.w = g->entity->frames[i]->w;
        g->entity->xy_hw.h = g->entity->frames[i]->h;

        if(SDL_GetTicks() - g->ticks[ENTITY_1] > 0.001) {
            SDL_BlitSurface(g->entity->frames[i], NULL, g->screen, &(g->entity->xy_hw));
            SDL_UpdateRect(g->screen, g->entity->xy_hw.x, g->entity->xy_hw.y,
                g->entity->frames[i]->w, g->entity->frames[i]->h); 

            g->ticks[ENTITY_1] = SDL_GetTicks();
            i++;
            // SDL_FillRect(g->screen, &(g->entity->xy_hw), SDL_MapRGB(g->screen->format, 0, 0, 0));
            // SDL_UpdateRect(g->screen, g->entity->xy_hw.x, g->entity->xy_hw.y,
            //        g->entity->frames[i]->w, g->entity->frames[i]->h); 
        }
    }

    return 0;
}

int game_main_loop(Game *g)
{
    SDL_Event ev;
    while(1) {
        treat(RENDER_GAME, g, render_game(g));
        treat(EVENT_PROCESS, g, event_process(g, &ev));
    }
}
 
int quit_game(Game *g)
{
    destroy_game(g);
    SDL_Quit();
    exit(0);
}


